--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
vendor/rns_filesync/README.md c0b0ddffd735a0d007c1be9a5e8563ec42fdafc0 (c0b0ddff) Text, 6.75 KB
RNS FileSync
Decentralized peer-to-peer file synchronization over the Reticulum Network Stack.
This package is designed as an embeddable library for host programs such as
MeshChatX and Sideband, with a thin CLI for standalone use. There is no TUI.
For usability and easy usage this follows rngit permissions and configuration.
Features
• Peer-to-peer sync with no central server
• Delta sync for changed blocks
• Path-jailed writes and rngit-style ACL (permission:target)
• Embed-safe: reuses an existing RNS.Reticulum instance when present
• Works over any Reticulum medium (radio, LoRa, WiFi, internet)
• Daemon mode via --no-repl for init systems and containers
Install
Over Reticulum with pip-rns (no internet required once you have a path):
T282828
pip-rns install rns://06a54b505bb67b25ef3f8097e8001edc/public/rns-filesync --pipx
From a release wheel over Reticulum (no source build):
T282828
pip-rns install --from-release rns://06a54b505bb67b25ef3f8097e8001edc/public/rns-filesync --ref v1.0.0 --pipx
From GitHub with pipx:
T282828
pipx install git+https://github.com/Quad4-Software/RNS-Filesync
From a local wheel:
T282828
make wheel
pipx install dist/rns_filesync-*.whl
T8b949e# or: pip install dist/rns_filesync-*.whl
From a local checkout (development):
T282828
pip install -e Ta5d6ff".[dev]"
T8b949e# or: make install-user
Requires rns>=1.4.0. Current package version: 1.0.0.
T282828
rns-filesync -v
T8b949e# rns-filesync 1.0.0 | built 2026-07-19T12:00:00Z | commit abc1234
Config
FileSync uses an rngit-like config directory (default T383838~/.rns_filesync/):
T282828
rns-filesync -d ~/shared
T8b949e# creates ~/.rns_filesync/config on first run
┌─────────────────┬─────────────────────────────────────────────────────┐
│ Flag │ Meaning │
├─────────────────┼─────────────────────────────────────────────────────┤
│ T383838--config DIR │ FileSync config directory (default T383838~/.rns_filesync) │
│ T383838--rnsconfig DIR │ Reticulum config directory (default T383838~/.reticulum) │
│ T383838-d DIR │ Sync directory (overrides T383838[filesync] directory) │
└─────────────────┴─────────────────────────────────────────────────────┘
Example T383838~/.rns_filesync/config:
T282828
Tff7b72[filesync]
Te6edf3announce_interval Tff7b72= Ta5d6ff300
T8b949e# directory = ~/shared
Te6edf3identity Tff7b72= Ta5d6ffrns_filesync
T8b949e# peers = 9710b86ba12c42d1d8f30f74fe509286
T8b949e# blocked_identities = d31aeea49873006f13b3415520666a4e
Tff7b72[aliases]
T8b949e# alice = d09285e660cfe27cee6d9a0beb58b7e0
Tff7b72[access]
T8b949e# sync = r:all, w:9710b86ba12c42d1d8f30f74fe509286, d:9710b86ba12c42d1d8f30f74fe509286
Tff7b72[logging]
Te6edf3loglevel Tff7b72= Ta5d6ff4
Identities are stored under T383838~/.rns_filesync/identities/.
Permissions
Same rule form as rngit: T383838permission:target.
┌──────┬───────────────────┐
│ Perm │ Meaning │
├──────┼───────────────────┤
│ T383838r │ read │
│ T383838w │ write │
│ T383838d │ delete │
│ T383838rw │ read/write │
│ T383838rwd │ read/write/delete │
│ T383838adm │ admin (all) │
└──────┴───────────────────┘
Targets: identity hash, alias, T383838all, or T383838none.
When any ACL rule is loaded, access is deny by default. With no rules configured, the peer stays open (library/embed default).
Sidecar T383838.allowed files (first found wins alongside config T383838[access]):
• T383838<sync_dir>.allowed
• T383838<parent>/<name>.allowed
• T383838<sync_dir>/.allowed
See T383838permissions.example.
T282828
rns-filesync -d ~/shared --allow r:all --allow w:9710b86ba12c42d1d8f30f74fe509286
CLI
T282828
rns-filesync -d ~/shared
rns-filesync -d ~/shared -p <peer_identity_hash>
rns-filesync --config ~/.rns_filesync --rnsconfig ~/.reticulum -d ~/shared
rns-filesync -v
rns-filesync --version
T383838-v / T383838--version prints version, bake build date, and git commit when available.
T383838-p expects a peer identity hash. A destination hash is accepted as fallback
after the peer has announced.
Interactive commands: T383838status, T383838peers, T383838files, T383838connect, T383838disconnect,
T383838browse, T383838download, T383838announce, T383838quit.
Logging verbosity uses T383838--verbose (repeatable). Quiet mode is T383838-q.
Man page
T282828
make install-user T8b949e# installs man page to ~/.local/share/man/man1/
man rns-filesync
Library embed (MeshChatX-style)
T282828
Tff7b72from T7ee787rns_filesync Tff7b72import Te6edf3FileSyncService
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787permissions Tff7b72import Te6edf3PermissionStore
Te6edf3perms Tff7b72= Te6edf3PermissionStoreTb4b4b4(Tb4b4b4)
Te6edf3permsTff7b72.Td2a8ffadd_ruleTb4b4b4(Ta5d6ff"Ta5d6ffr:allTa5d6ff"Tb4b4b4)
Te6edf3permsTff7b72.Td2a8ffadd_ruleTb4b4b4(Ta5d6ff"Ta5d6ffw:9710b86ba12c42d1d8f30f74fe509286Ta5d6ff"Tb4b4b4)
Te6edf3service Tff7b72= Te6edf3FileSyncServiceTb4b4b4(
Te6edf3identityTff7b72=Te6edf3host_identityTb4b4b4,
Te6edf3sync_directoryTff7b72=Ta5d6ff"Ta5d6ff/path/to/syncTa5d6ff"Tb4b4b4,
Te6edf3reticulumTff7b72=Te6edf3existing_reticulumTb4b4b4,
Te6edf3permissionsTff7b72=Te6edf3permsTb4b4b4,
Tb4b4b4)
Te6edf3dest_hash Tff7b72= Te6edf3serviceTff7b72.Td2a8ffstartTb4b4b4(Te6edf3monitorTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3serviceTff7b72.Td2a8ffconnect_peerTb4b4b4(Te6edf3peer_identity_hashTb4b4b4)
Te6edf3serviceTff7b72.Td2a8ffstopTb4b4b4(Tb4b4b4)
Keep aspect T383838rns_filesync.filesync for wire compatibility.
Sideband plugin
Install T383838rns-filesync into the same Python environment Sideband uses, then copy
the drop-in plugins from T383838sideband/ into Sideband's plugins directory and
enable service/command plugins in Sideband settings.
T282828
T8b949e# After installing rns-filesync (pip / pipx / pip-rns):
cp sideband/rns_filesync_service.py ~/.config/sideband/plugins/
cp sideband/rns_filesync_command.py ~/.config/sideband/plugins/
Set Sideband's plugin path to that directory, enable service plugins and
command plugins, then restart Sideband.
The service plugin reuses Sideband's identity and Reticulum instance. Sync
directory, peers, and ACL come from T383838~/.rns_filesync/config. If no directory
is set there, it defaults to T383838~/.config/sideband/filesync.
Remote LXMF commands (from a peer allowed to run Sideband commands):
T282828
filesync status
filesync peers
filesync files
filesync announce
filesync connect <identity_hash>
filesync disconnect <peer_id>
Daemon and packaging
Init units (non-root) live under packaging/ for systemd (system and user),
OpenRC, dinit, and runit. See packaging/README.md.
T282828
T8b949e# system (dedicated rns-filesync user, hardened)
sudo systemctl Tffa657enable --now rns-filesync
T8b949e# or per-user
systemctl --user Tffa657enable --now rns-filesync
Daemon entrypoint:
T282828
rns-filesync -d ~/shared --no-repl -q
Bubblewrap sandbox example (full command in packaging/README.md):
T282828
Te6edf3DATATff7b72=Ta5d6ff"Tffd700${Te6edf3XDG_DATA_HOMETff7b72:-Te6edf3$HOMETb4b4b4/.local/shareTffd700}Ta5d6ff/rns-filesync-sandboxTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$DATATa5d6ff/configTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/syncTa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff/reticulumTa5d6ff"
Tffa657exec bwrap Tffea00\
--die-with-parent Tffea00\
--new-session Tffea00\
--proc /proc Tffea00\
--dev /dev Tffea00\
--ro-bind / / Tffea00\
--tmpfs /tmp Tffea00\
--bind Ta5d6ff"Te6edf3$DATATa5d6ff" Ta5d6ff"Te6edf3$DATATa5d6ff" Tffea00\
--uid Ta5d6ff"Tff7b72$(id -uTff7b72)Ta5d6ff" --gid Ta5d6ff"Tff7b72$(id -gTff7b72)Ta5d6ff" Tffea00\
rns-filesync Tffea00\
--config Ta5d6ff"Te6edf3$DATATa5d6ff/configTa5d6ff" Tffea00\
--rnsconfig Ta5d6ff"Te6edf3$DATATa5d6ff/reticulumTa5d6ff" Tffea00\
-d Ta5d6ff"Te6edf3$DATATa5d6ff/syncTa5d6ff" Tffea00\
--no-repl Tffea00\
-q
Docker
Rootless multi-stage image and wheel builder under docker/. See docker/README.md.
T282828
docker build -f docker/Dockerfile -t rns-filesync:1.0.0 .
Tests
T282828
make Tffa657test
pytest -m Ta5d6ff"not live and not exploratory"
pytest -m e2e
pytest -m live
Markers: T383838unit, T383838acceptance, T383838smoke, T383838e2e, T383838fuzz, T383838live, T383838exploratory.
Useful Make targets (aligned with pip-rns): T383838meta, T383838wheel, T383838sdist, T383838test,
T383838install-user, T383838man, T383838sign, T383838release-rns, T383838clean, T383838test-services.
License
BSD-2-Clause. See LICENSE.
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────